package com.hyw.trace.configuration.collector.meta.mq;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;

import com.hyw.trace.configuration.meta.mq.binder.ZTraceSink;

/**
 * 如果 MQ feature启用, 则对 stream 进行配置
 * 
 * @author hongyu
 */
public class CollectorStreamEnvironmentPostProcessor implements EnvironmentPostProcessor {

  private static final String PROPERTY_SOURCE_NAME = "ztraceCollectorStreamDefaultProperties";

  @Override
  public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
    Map<String, Object> map = new HashMap<>(3);
    String type = environment.getProperty("ztrace.server.meta.receive.type");
    boolean isMatch = StringUtils.isEmpty(type) || Objects.equals("MQ", type.toUpperCase());
    if (isMatch) {
      map.put("spring.cloud.stream.bindings." + ZTraceSink.INPUT + ".destination", ZTraceSink.INPUT);
      map.put("spring.cloud.stream.bindings." + ZTraceSink.INPUT + ".contentType", "application/json");
      map.put("spring.cloud.stream.bindings." + ZTraceSink.INPUT + ".group", ZTraceSink.INPUT);
    }
    addOrReplace(environment.getPropertySources(), map);
  }

  private void addOrReplace(MutablePropertySources propertySources, Map<String, Object> map) {
    MapPropertySource target = null;
    if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
      PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
      if (source instanceof MapPropertySource) {
        target = (MapPropertySource) source;
        // 强制添加或者替换
        for (Entry<String, Object> e : map.entrySet()) {
          target.getSource().put(e.getKey(), e.getValue());
        }
      }
    }
    if (target == null) {
      target = new MapPropertySource(PROPERTY_SOURCE_NAME, map);
    }
    if (!propertySources.contains(PROPERTY_SOURCE_NAME)) {
      propertySources.addLast(target);
    }
  }

}
